Visualising FHIR Ontology using JSONFile

Given the json file containing nodes and edges, we can visualise the entire fhir ontology using python interactive tool i.e. plotly

# Identify and extract the classes and properties from the FHIR ontology.

import pickle
from personal_graph.helper import extract_classes_properties

# Dumping the fhir ontology's classes and properties
node_types_info = extract_classes_properties()
file = open("ontology_classes_and_properties.pkl", "wb")
pickled_data = pickle.dumps(node_types_info)
file.write(pickled_data)
file.close()
# Create a JSON file that includes a list of nodes and edges representing the FHIR ontology.

import os
import json
import pickle

from personal_graph.extract_classes import extract_classes_properties
from personal_graph.helper import get_type_name

pickle_filename = "ontology_classes_and_properties.pkl"
json_filename = "fhir_ontology.json"
try:
    # Check if the pickle file exists
    if os.path.exists(pickle_filename):
        print("Loading FHIR node data from pickle file...")
        with open(pickle_filename, "rb") as f:
            node_types_info = pickle.load(f)
    else:
        node_types_info = extract_classes_properties()

    ontology_data = {"nodes": [], "edges": []}

    # Add all node_types
    for node_type in node_types_info.keys():
        ontology_data["nodes"].append({"id": node_type, "label": node_type})

    # Create edges between node_types with other related node_types
    for node_type, properties in node_types_info.items():
        for prop, prop_type in properties.items():
            type_name = get_type_name(prop_type)
            if type_name in node_types_info.keys():
                # This property is a FHIR resource type, create an edge of 'instance_of'
                ontology_data["edges"].append(
                    {"source": node_type, "target": type_name, "label": prop}
                )

    # Save the ontology data as JSON
    with open(json_filename, "w") as f:
        json.dump(ontology_data, f, indent=2)

    print(f"FHIR ontology data saved to {json_filename}")

except Exception as e:
    print(f"An error occurred: {e}")
    raise e
Loading FHIR node data from pickle file...
FHIR ontology data saved to fhir_ontology.json
# Visualise the FHIR Ontology using interactive tool 'plotly'

import json
import networkx as nx

import plotly.graph_objects as go  # type: ignore
from plotly.io import write_html  # type: ignore

# Load the JSON data
with open("fhir_ontology.json", "r") as f:
    ontology_data = json.load(f)

# Create a NetworkX graph
G = nx.MultiGraph()

# Add nodes and edges to the graph
for node in ontology_data["nodes"]:
    G.add_node(node["id"], label=node["label"])

for edge in ontology_data["edges"]:
    G.add_edge(edge["source"], edge["target"], label=edge["label"])

# Get node positions using a layout algorithm
pos = nx.spring_layout(G, k=0.5, iterations=50)

# Create edge trace
edge_traces = []
for edge in G.edges(data=True):
    x0, y0 = pos[edge[0]]
    x1, y1 = pos[edge[1]]

    edge_trace = go.Scatter(
        x=[x0, x1, None],
        y=[y0, y1, None],
        line=dict(width=0.5, color="#888"),
        hoverinfo="text",
        mode="lines+text",
        text=[edge[2]["label"]],
        textposition="middle center",
        textfont=dict(size=8),
    )
    edge_traces.append(edge_trace)

    # Add edge label
    edge_label_trace = go.Scatter(
        x=[(x0 + x1) / 2],
        y=[(y0 + y1) / 2],
        mode="text",
        text=[edge[2]["label"]],
        textposition="middle center",
        textfont=dict(size=8, color="red"),
        hoverinfo="none",
    )
    edge_traces.append(edge_label_trace)

# Create node trace
node_x = []
node_y = []
for node in G.nodes():
    x, y = pos[node]
    node_x.append(x)
    node_y.append(y)

node_trace = go.Scatter(
    x=node_x,
    y=node_y,
    mode="markers+text",
    hoverinfo="text",
    text=[
        f"{node}<br># of connections: {len(list(G.edges(node)))}"
        for node in G.nodes()
    ],
    textposition="top center",
    textfont=dict(size=8),
    marker=dict(
        showscale=True,
        colorscale="YlGnBu",
        size=10,
        color=[len(list(G.neighbors(node))) for node in G.nodes()],
        colorbar=dict(
            thickness=15,
            title="Node Connections",
            xanchor="left",
            titleside="right",
        ),
    ),
)

# Create the figure
fig = go.Figure(
    data=edge_traces + [node_trace],
    layout=go.Layout(
        title="FHIR Ontology Network Graph",
        titlefont_size=16,
        showlegend=False,
        hovermode="closest",
        margin=dict(b=20, l=5, r=5, t=40),
        annotations=[
            dict(
                text="FHIR Ontology",
                showarrow=False,
                xref="paper",
                yref="paper",
                x=0.005,
                y=-0.002,
            )
        ],
        xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
        yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
    ),
)
fig.show()